#include<iostream>
#include "../comm/httplib.h"
#include "../comm/mysql_util.hpp"
#include "../comm/session_manager.hpp"
#include "oj_control.hpp"
#include <signal.h>

using namespace httplib;
using namespace ns_control;
using namespace ns_session;


static Control *ctrl_ptr=nullptr;

static SessionManager session_mgr;

void Recovery(int sig)
{
    LOG(INFO) << "收到信号: " << sig << "，正在恢复所有离线主机...\n";
    ctrl_ptr->RecoveryMachine(); // 恢复所有离线主机
    LOG(INFO) << "所有离线主机已恢复\n";
}

// 检查用户是否已登录（通过Cookie中的会话ID）
bool IsLogin(const Request& req, std::string* username) {
    auto it = req.headers.find("Cookie");
    if (it == req.headers.end()) {
        return false;
    }
    std::string cookie = it->second;
    // 从Cookie中提取会话ID（格式：session_id=xxx）
    size_t pos = cookie.find("session_id=");
    if (pos == std::string::npos) {
        return false;
    }
    std::string session_id = cookie.substr(pos + 10);  // "session_id="长度为10
    // 验证会话ID并获取用户名
    return session_mgr.Get(session_id, username);
}

int main()
{
    signal(SIGQUIT,Recovery);
    //用户请求服务路由功能
    Server svr;
    Control ctrl;
    ctrl_ptr = &ctrl; // 将控制器指针赋值给全局变量



    // 返回注册页面
svr.Get("/register", [](const Request& req, Response& resp) {
    // 读取 wwwroot/register.html
    std::string html;
    FILE* fp = fopen("wwwroot/register.html", "r");
    if (!fp) {
        resp.set_content("注册页面不存在", "text/html;charset=utf-8");
        return;
    }
    char buf[1024];
    while (fgets(buf, sizeof(buf), fp)) {
        html += buf;
    }
    fclose(fp);
    resp.set_content(html, "text/html;charset=utf-8");
});

// 处理注册表单提交
svr.Post("/register", [](const Request& req, Response& resp) {
    // 解析表单数据 username=xxx&password=yyy
    std::string username, password;
    auto body = req.body;
    size_t pos = body.find("username=");
    if (pos != std::string::npos) {
        size_t end = body.find("&", pos);
        username = body.substr(pos + 9, end - (pos + 9));
    }
    pos = body.find("password=");
    if (pos != std::string::npos) {
        size_t end = body.find("&", pos);
        if (end == std::string::npos) end = body.size();
        password = body.substr(pos + 9, end - (pos + 9));
    }

    // 简单校验
    if (username.empty() || password.empty()) {
        resp.set_content("<h1>用户名或密码不能为空</h1><meta http-equiv='refresh' content='2;url=/register'>", "text/html;charset=utf-8");
        return;
    }

    try {
        MySQLUtil mysql("localhost", "root", "你的MySQL密码", "oj_db");
        if (mysql.RegisterUser(username, password)) {
            resp.set_content("<h1>注册成功！2秒后跳转到登录页</h1><meta http-equiv='refresh' content='2;url=/login'>", "text/html;charset=utf-8");
        } else {
            resp.set_content("<h1>用户名已存在</h1><meta http-equiv='refresh' content='2;url=/register'>", "text/html;charset=utf-8");
        }
    } catch (const std::exception& e) {
        resp.set_content("<h1>注册失败: " + std::string(e.what()) + "</h1>", "text/html;charset=utf-8");
    }
});

    
    // 返回登录页面
    svr.Get("/login", [](const Request& req, Response& resp) {
        std::string html;
        FILE* fp = fopen("wwwroot/login.html", "r");
        if (!fp) {
            resp.set_content("登录页面不存在", "text/html;charset=utf-8");
            return;
        }
        char buf[1024];
        while (fgets(buf, sizeof(buf), fp)) {
            html += buf;
        }
        fclose(fp);
        resp.set_content(html, "text/html;charset=utf-8");
    });

    // 处理登录表单提交
    svr.Post("/login", [](const Request& req, Response& resp) {
        // 解析表单数据（username=xxx&password=yyy）
        std::string username, password;
        auto body = req.body;
        
        // 提取用户名
        size_t pos = body.find("username=");
        if (pos != std::string::npos) {
            size_t end = body.find("&", pos);
            username = body.substr(pos + 9, end - (pos + 9));  // "username="长度为9
        }
        // 提取密码
        pos = body.find("password=");
        if (pos != std::string::npos) {
            size_t end = body.find("&", pos);
            if (end == std::string::npos) end = body.size();
            password = body.substr(pos + 9, end - (pos + 9));  // "password="长度为9
        }

        // 简单校验
        if (username.empty() || password.empty()) {
            resp.set_content(
                "<h1>用户名或密码不能为空</h1>"
                "<meta http-equiv='refresh' content='2;url=/login'>", 
                "text/html;charset=utf-8"
            );
            return;
        }

        try {
            // 连接数据库验证用户
            MySQLUtil mysql("localhost", "root", "你的MySQL密码", "oj_db");
            // 1. 获取数据库中存储的加密密码（假设用户表为user，密码字段为password）
            std::string stored_pwd;
            if (!mysql.GetUserPassword(username, &stored_pwd)) {
                // 用户名不存在
                resp.set_content(
                    "<h1>用户名不存在</h1>"
                    "<meta http-equiv='refresh' content='2;url=/login'>", 
                    "text/html;charset=utf-8"
                );
                return;
            }
            // 2. 对用户输入的密码进行SHA256加密（与注册时一致）
            std::string input_pwd = MySQLUtil::SHA256(password);
            // 3. 比对加密后的密码
            if (input_pwd == stored_pwd) {
                // 登录成功：创建会话
                std::string session_id = session_mgr.Create(username);  // 生成会话ID并关联用户名
                // 设置Cookie（会话ID，有效期2小时）
                resp.set_header("Set-Cookie", 
                    "session_id=" + session_id + "; Max-Age=7200; Path=/");
                // 跳转到题库页面
                resp.set_content(
                    "<h1>登录成功！2秒后跳转到题库</h1>"
                    "<meta http-equiv='refresh' content='2;url=/all_questions'>", 
                    "text/html;charset=utf-8"
                );
            } else {
                // 密码错误
                resp.set_content(
                    "<h1>密码错误</h1>"
                    "<meta http-equiv='refresh' content='2;url=/login'>", 
                    "text/html;charset=utf-8"
                );
            }
        } catch (const std::exception& e) {
            resp.set_content(
                "<h1>登录失败: " + std::string(e.what()) + "</h1>", 
                "text/html;charset=utf-8"
            );
        }
    });

    // 注销功能
    svr.Get("/logout", [](const Request& req, Response& resp) {
        auto it = req.headers.find("Cookie");
        if (it != req.headers.end()) {
            std::string cookie = it->second;
            size_t pos = cookie.find("session_id=");
            if (pos != std::string::npos) {
                std::string session_id = cookie.substr(pos + 10);
                session_mgr.Destroy(session_id);  // 销毁会话
            }
        }
        // 清除Cookie并跳转到登录页
        resp.set_header("Set-Cookie", "session_id=; Max-Age=0; Path=/");
        resp.set_content(
            "<h1>已注销！2秒后跳转到登录页</h1>"
            "<meta http-equiv='refresh' content='2;url=/login'>", 
            "text/html;charset=utf-8"
        );
    });

    // 限制未登录用户访问题库和提交代码
    // 获取所有题目列表（需登录）
    svr.Get("/all_questions", [&ctrl](const Request &req, Response &resp) {
        std::string username;
        if (!IsLogin(req, &username)) {
            // 未登录，跳转到登录页
            resp.set_content(
                "<h1>请先登录</h1>"
                "<meta http-equiv='refresh' content='2;url=/login'>", 
                "text/html;charset=utf-8"
            );
            return;
        }
        // 已登录，正常返回题库
        std::string html;
        ctrl.AllQuestions(&html);
        resp.set_content(html, "text/html;charset=utf-8");
    });

    // 获取题目内容（需登录）
    svr.Get(R"(/question/(\d+))",[&ctrl](const Request &req, Response &resp) {
        std::string username;
        if (!IsLogin(req, &username)) {
            resp.set_content(
                "<h1>请先登录</h1>"
                "<meta http-equiv='refresh' content='2;url=/login'>", 
                "text/html;charset=utf-8"
            );
            return;
        }
        std::string number = req.matches[1];
        std::string html;
        ctrl.Question(number, &html);
        resp.set_content(html, "text/html;charset=utf-8");
    });

    // 提交代码判题（需登录）
    svr.Post(R"(/judge/(\d+))", [&ctrl](const Request &req, Response &resp) {
        std::string username;
        if (!IsLogin(req, &username)) {
            resp.set_content(
                R"({"status": -1, "reason": "请先登录"})", 
                "application/json;charset=utf-8"
            );
            return;
        }
        std::string number = req.matches[1];
        std::string result_json;
        ctrl.Judge(number, req.body, &result_json);
        resp.set_content(result_json, "application/json;charset=utf-8");
    });
    svr.set_base_dir("./wwwroot"); // 设置静态文件目录
    svr.listen("0.0.0.0", 8080); // 启动http服务，监听所有IP的8080端口
    return 0;
}